﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;

namespace ex_2
{
    public partial class Form1 : Form
    {
        //记录接收的字节数
        private long receive_count = 0;
        //记录发送的字节数
        private long send_count = 0;
        //字符串构造类型，用于将读取到的字节类型转换为字符串类型
        private StringBuilder sbuilder = new StringBuilder();
        //记录当前时间
        private DateTime current_time = new DateTime();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //设置波特率
            for (int i = 300; i <= 150000; i *= 2)
            {
                comboBox2.Items.Add(i.ToString());
            }
            //设置默认值
            comboBox1.Text = "COM1";
            comboBox2.Text = "19200";
            comboBox3.Text = "8";
            comboBox4.Text = "None";
            comboBox5.Text = "one";

            comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
        }

        //打开或关闭串口
        private void button1_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                //原本是开着的，点击后要关闭
                serialPort1.Close();
                button1.Text = "打开串口";
                button1.BackColor = Color.SkyBlue;
                comboBox1.Enabled = true;
                comboBox2.Enabled = true;
                comboBox3.Enabled = true;
                comboBox4.Enabled = true;
                comboBox5.Enabled = true;

                label6.Text = "串口已关闭";
                label6.ForeColor = Color.Gray;
            }
            else
            {
                //原本是开着的，点击后打开
                button1.Text = "关闭串口";
                button1.BackColor = Color.Gray;
                comboBox1.Enabled = false;
                comboBox2.Enabled = false;
                comboBox3.Enabled = false;
                comboBox4.Enabled = false;
                comboBox5.Enabled = false;
                serialPort1.PortName = comboBox1.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);
                String str1 = comboBox4.Text;
                String str2 = comboBox5.Text;
                if (str1.Equals("None"))
                {
                    serialPort1.Parity = Parity.None;
                }
                else if (str1.Equals("Even"))
                {
                    serialPort1.Parity = Parity.Even;
                }
                else if (str1.Equals("Mark"))
                {
                    serialPort1.Parity = Parity.Mark;
                }
                else if (str1.Equals("Odd"))
                {
                    serialPort1.Parity = Parity.Odd;
                }
                if (str2.Equals("One"))
                {
                    serialPort1.StopBits = StopBits.One;
                }
                else if (str2.Equals("OnePointFive"))
                {
                    serialPort1.StopBits = StopBits.OnePointFive;
                }
                else if (str2.Equals("Two"))
                {
                    serialPort1.StopBits = StopBits.Two;
                }
                serialPort1.Open();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //清空接收数据
            textBox1.Clear();
            receive_count = 0;
            label7.Text = "Rx:" + receive_count.ToString() + "Bytes";
        }

        //发送数据
        private void button3_Click(object sender, EventArgs e)
        {
            byte[] temp = new byte[1];
            if (serialPort1.IsOpen)
            {
                int num = 1;
                //以ASCII方式发送
                if (radioButton3.Checked)
                {
                    //自动换行
                    if (checkBox2.Checked)
                    {
                        //自动发送断行
                        serialPort1.WriteLine(textBox2.Text);
                        num = textBox1.Text.Length + 2; //回车占两个字节
                    }
                    //不自动换行
                    else
                    {
                        serialPort1.Write(textBox2.Text);
                        num = textBox1.Text.Length;
                    }
                }
                //以Hex方式发送
                else
                {
                    string buf = textBox2.Text;
                    string pattern = @"\s";
                    string replacement = "";
                    Regex rgx = new Regex(pattern);
                    string send_data = rgx.Replace(buf, replacement);
                    num = (send_data.Length - send_data.Length % 2) / 2;
                    for (int i = 0; i < num; i++)
                    {
                        temp[0] = Convert.ToByte(send_data.Substring(i * 2, 2), 16);
                        serialPort1.Write(temp, 0, 1);  //循环发送
                    }
                    if (send_data.Length % 2 != 0)
                    {
                        temp[0] = Convert.ToByte(send_data.Substring(textBox2.Text.Length, 1), 16);
                        serialPort1.Write(temp, 0, 1);
                        num++;
                    }
                    if (checkBox2.Checked)
                    {
                        serialPort1.WriteLine("");
                    }
                }
                current_time = System.DateTime.Now;
                textBox1.AppendText("[SENT]" + current_time.ToString("yyyy/MMM/dd H:mm:ss") + " " + textBox2 + "\r\n");
                send_count += num;
                label8.Text = "Tx:" + send_count.ToString() + "Bytes";
            }
        }

        //接收数据
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int num = serialPort1.BytesToRead;
            byte[] received_buf = new byte[num];
            receive_count += num;
            serialPort1.Read(received_buf, 0, num);

            sbuilder.Clear();
            //选中HEX接收模式
            if (radioButton2.Checked)
            {
                foreach (byte b in received_buf)
                {
                    sbuilder.Append(b.ToString("X2") + ' ');
                }
            }
            //选中ASCII接收模式
            else
            {
                sbuilder.Append(Encoding.ASCII.GetString(received_buf));
            }

            Invoke((EventHandler)(delegate
            {
                //不显示时间
                if (checkBox1.Checked)
                {
                    textBox1.AppendText(sbuilder.ToString() + "\r\n");
                }
                //显示时间
                else
                {
                    current_time = System.DateTime.Now;  //获取当前时间
                    textBox1.AppendText("[RECV]" + current_time.ToString("yyyy/MM/dd HH:mm:ss") + "" + sbuilder.ToString() + "\r\n");
                }
                label7.Text = "rx:" + receive_count.ToString() + "bytes";
            }
        )
        );
        }

        private void checkBox3_CheckChanged(object sender, EventArgs e)
        {
            //自动发送
            if (checkBox3.Checked)
            {
                numericUpDown1.Enabled = false;
                timer1.Interval = (int)numericUpDown1.Value;
                timer1.Start();
                label6.Text = "串口已打开" + "自动发送中...";
                label6.ForeColor = Color.Gray;
            }
            //非自动发送
            else
            {
                numericUpDown1.Enabled = true;
                timer1.Stop();
                label6.Text = "串口已打开";
                label6.ForeColor = Color.Gray;
            }
        }

        private void checkBox2_CheckChanged(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            button3_Click(button3, new EventArgs());
        }
    }
}